package domain

import (
	"errors"
	"time"
)

type Product struct {
	id          int     `comment:"唯一标识"`
	name        string  `comment:"名称"`
	price       float32 `comment:"价格"`
	stock       int     `comment:"库存"`
	description string  `comment:"描述"`
	image       string  `comment:"商品图片的链接"`

	createTime time.Time `comment:"创建时间"`
	updateTime time.Time `comment:"修改时间"`

	Status Status `comment:"商品状态"`
}

func NewProduct(
	id int,
	name string,
	price float32,
	stock int,
	description string,
	image string,
	status Status,
) (*Product, error) {

	// 参数校验放在领域层
	err := productCheck(
		id,
		name,
		price,
		stock,
		description,
		image,
		status)
	if err != nil {
		return nil, err
	}

	return &Product{
		id:          id,
		name:        name,
		price:       price,
		stock:       stock,
		description: description,
		image:       image,
		createTime:  time.Now(),
		updateTime:  time.Now(),
	}, nil
}

func productCheck(
	id int,
	name string,
	price float32,
	stock int,
	description string,
	image string,
	s Status,
) error {
	// params checking
	if name == "" {
		return errors.New("empty product name")
	}
	if price == 0 {
		return errors.New("empty product price")
	}
	if stock == 0 {
		return errors.New("empty product stock")
	}
	if description == "" {
		return errors.New("empty product description")
	}
	if image == "" {
		return errors.New("empty product image")
	}
	if s.IsEmpty() {
		return errors.New("empty Status")
	}
	if !s.Equal(Normal) || !s.Equal(Deleted) {
		return errors.New("invalid Status")
	}

	return nil
}

func (p Product) IsAvailable() bool {
	return p.stock > 0
}

func (p Product) SetStatus(s Status) {
	p.Status = s
}

func (p Product) StatusEqual(s Status) bool {
	return p.Status == s
}

func (p Product) Id() int {
	return p.id
}

func (p Product) Name() string {
	return p.name
}

func (p Product) Price() float32 {
	return p.price
}

func (p Product) Stock() int {
	return p.stock
}

func (p Product) Description() string {
	return p.description
}

func (p Product) Image() string {
	return p.image
}

func (p Product) CreateTime() time.Time {
	return p.createTime
}

func (p Product) UpdateTime() time.Time {
	return p.updateTime
}
